# -*- coding: UTF-8 -*-
# @Time      : 2022/6/15 16:17
# @Author    : IT Pyramid
# @File      : authentication
import sys
import time
from datetime import datetime
import json
import schedule
import os
import base64
from Crypto.Cipher import PKCS1_v1_5
from Crypto import Random
from Crypto.PublicKey import RSA
import uuid
from threading import Thread

import uvicorn


class Authentication:

    def __init__(self):
        if self.get_platform() == "linux":
            self.project_path = "/home/project/"
        elif self.get_platform() == "win":
            self.project_path = "C:/project/"
        self.public_key = '-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzq1FZpTJo4gNUfQ7LgdtLhMFUtfB/N6weMJ2XaAsl4Hmmx56Z8YO+jBB9HiZU7bDXG83GZWXEF+SSzGj+3T9O+vhXpvKxpuptr8QSvVInx5zdxE8G6fd4/4f9jklnVf1JvODiTtiv08R37vGoxdgvkcp+/i7+bpurz1FOQRMHJ5sstGMTO2E//4IKtIzZl7qafc+BbPCRAKQdBX/SOCzydTCLH61ZzoV64g2rq4c+i/lnkfpE6MdT+yOsS/IHpRDwLxPiPcpfUGgC4nCrqWueyWGx04o7T0HGo3otprF/E8JmKsiM3T+6T6+v6JEPoFPsqJKKDgPRuN5HJbBBfWJbZJNOcKnpfWPVRv5ZjNJGiwrZ2IDCLeyK8Ee2iFrLiqFVFhEdWvxkE3N6FaGezfh7gE6FJXatHU3Dh2LPo+SwtiqpalheSoO3nmlvBA8U/vk5OeVXv+aMK/OEDHN1FhXJ+NjyOgyfV5e0fWpstbgboEVW8LcnYik2Zwxb4yrKV+LYQJqu/buFdNrL6SeYeEJx8TfniqvWEUlNP1qJf7Tc4+giUcGuFN/7GpPcoMeS8FeW07HHMUI9TM2176p74PjQIvl/RzKDm15VCJJobY3Mw8D5/QuITNJWeDkutrZGc9fTSNkn2coFqjEQ1aqJ6jLbkNDi8Il4XeJblnT+aUhSM0CAwEAAQ==\n-----END PUBLIC KEY-----'
        self.private_key = '-----BEGIN PRIVATE KEY-----\n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\n-----END PRIVATE KEY-----'

    @staticmethod
    def get_platform():
        """
        获取当前操作系统
        """
        platform = sys.platform
        if "linux" in platform:
            return "linux"
        elif "win" in platform:
            return "win"
        return None

    def get_cpu(self):
        """
        获取CPU序列号
        """
        try:
            cpu = None
            if self.get_platform() == "win":
                import wmi
                c = wmi.WMI()
                # CPU序列号
                for index, cpu in enumerate(c.Win32_Processor()):
                    # print("CPU {0} 序列号：{1}".format(index, cpu.ProcessorId.strip()))
                    cpu = cpu.ProcessorId.strip()
            elif self.get_platform() == "linux":
                cpu = "".join(os.popen("dmidecode -t 4 | grep ID |sort -u |awk -F': ' '{print $2}'").read().split())
            return cpu
        except Exception as e:
            print(e)
            raise Exception("获取CPU失败")

    @staticmethod
    def get_mac():
        """
        获取MAC地址
        """
        try:
            mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
            return mac
        except Exception:
            raise Exception("获取MAC失败")

    def decryption(self, text_encrypted_base64: str):
        """
        解密
        """
        try:
            # 字符串指定编码（转为bytes）
            text_encrypted_base64 = text_encrypted_base64.encode('utf-8')
            # base64解码
            text_encrypted = base64.b64decode(text_encrypted_base64)
            # 构建私钥对象
            cipher_private = PKCS1_v1_5.new(RSA.importKey(self.private_key))
            # 解密（bytes）
            text_decrypted = cipher_private.decrypt(text_encrypted, Random.new().read)
            # 解码为字符串
            text_decrypted = text_decrypted.decode()
            return text_decrypted
        except Exception:
            raise Exception("授权文件格式不正确")

    def encryption(self, text: str):
        # 字符串指定编码（转为bytes）
        text = text.encode('utf-8')
        # 构建公钥对象
        cipher_public = PKCS1_v1_5.new(RSA.importKey(self.public_key))
        # 加密（bytes）
        text_encrypted = cipher_public.encrypt(text)
        # base64编码，并转为字符串
        text_encrypted_base64 = base64.b64encode(text_encrypted).decode()
        return text_encrypted_base64

    def read_auth_file(self):
        """
        读取授权文件
        """
        path = os.path.join(os.getcwd(), "authorizeOut.txt")
        if not os.path.exists(path):
            raise FileExistsError("授权文件不存在")
        try:
            with open(path, 'r') as f:
                data = str(f.readlines())
            text_decrypted = json.loads(self.decryption(data))
            return text_decrypted
        except Exception:
            raise Exception("文件读取失败")

    def authentic(self):
        """
        项目激活
        """
        try:
            auth_data = self.read_auth_file()
            own_cpu = self.get_cpu()
            own_mac = self.get_mac()
            now_time = datetime.now()
            if not (auth_data['cpu'] == own_cpu and own_mac == auth_data['mac']):
                raise Exception("机型不匹配，项目激活失败")
            elif not datetime.strptime(auth_data['s_date'], "%Y/%m/%d") <= now_time <= datetime.strptime(
                    auth_data['e_date'], "%Y/%m/%d"):
                raise Exception("授权时间已到期，项目激活失败")
            auth_data.update({"res": True})
        except Exception as e:
            print(e)
            auth_data = {'res': False, 'error': e}
        return auth_data

    def start_project(self, app, window):
        """
        windows上使用进程启动项目
        :app: fastapi应用
        :window: QT窗体
        :return:
        """
        # try:
        #     window.qt_terminal.setPlainText("")
        #     auth_data = self.authentic()
        #     if not auth_data['res']:
        #         window.qt_terminal.insertPlainText("项目激活状态: {}\n原因: {}".format("未激活", auth_data['error']))
        #         return False
        #     window.qt_terminal.insertPlainText("\n设备校验通过，正在启动项目...\n")
        #     time.sleep(0.5)
        #     window.qt_terminal.insertPlainText("\n正在检测 8889 端口...\n")
        #     time.sleep(0.5)
        #     window.qt_terminal.insertPlainText("\n项目启动成功\n")
        #     if self.get_platform() == "linux":
        #         if os.popen("netstat -anp | grep 8889").read() == "":
        #             # uvicorn.run(app, host="127.0.0.1", port=8889, reload=False)
        #             os.system("uvicorn --host 127.0.0.1:8889 {} --lifespan on".format(app))
        #     elif self.get_platform() == "win":
        #         # print(os.popen("netstat -ano|findstr 8889").read() == "")
        #         if os.popen("netstat -ano|findstr 8889").read() == "":
        #             os.system("uvicorn --host 127.0.0.1:8889 {} --lifespan on".format(app))
        # except Exception as e:
        #     window.qt_terminal.setPlainText("\n项目启动失败，{}\n".format(e))

    def stop_project(self, window):
        """
        停止项目
        """
        window.qt_terminal.setPlainText("\n正在关闭 8889 端口...\n")
        try:
            if self.get_platform() == "linux":
                if not os.popen("netstat -anp | grep 8889").read() == "":
                    pid = os.popen("netstat -anp | grep 8889").read().split()[-1].split("/")[0]
                    os.popen("kill -9 %s" % pid)
            elif self.get_platform() == "win":
                if not os.popen("netstat -ano|findstr 8889").read() == "":
                    pid = os.popen("netstat -ano|findstr 8889").read().split()[-1].split("/")[0]
                    print("taskkill /pid %s -t -f" % pid)
                    try:
                        res = os.popen("taskkill /pid %s -t -f" % pid)
                    except Exception as e:
                        print(e)
            window.qt_terminal.setPlainText("\n项目关闭成功\n")
            return True
        except Exception as e:
            print(e)
            # window.qt_terminal.insertPlainText("\n" + e + "\n")
            return False

    def run(self):
        """
        每天早上10:30定时运行程序
        """
        res = self.authentic()
        schedule.every().day.at("15:31").do(self.authentic)
        # schedule.every().second.do(self.job)
        return res


if __name__ == "__main__":
    a = Authentication()
    print(a.decryption("ef4mfrj4mFRJDw8gWILVzGJYqdOM3UxS79JzW63pfayPPFmy+eLFlf4yFV5vgb9Sip0EitX+XdGV+SySz2foGOKPFD9IfoeLHZ8yVdvmOn7YufVgak9WpAqWBdWUJc8zrPLQspwdsC61URPmZse3rHz1UtY8KTFzcAQZEvsaZVeNCvpwC42xpezovH4WRxxziHavPKBCyycauwZ+ewUv5GjwP2EOUYxRTOjBf3jwHNo813aJ4GTGOi1mlWsO7pmm/zAj+XHjTFFAlS9VfzUmRakArBMvap4+WuQ/17pIkEOp5J9MC9OzUO7KniGApYsAoxb9mZQI0NjZfw7wMigQ67P0SbJn4Fu39uyg/G0Us2tge4ijY970GziSIAWWjGiqgLLwppzi0D7HNr55OZsbSnlIh+2SgtP6lZzjp9FFjSamgtpwydeNz2zwtGvS1JxGYWa174BVKjltjhXGvnuw6hGjUUfsmmlysv7xqap2knIfniLE+5OErZ6vqOMQMcZedcq3oruqeoZINYVQ8VTfEOK0SL7NOVvud2StdXMlF80PLqDDW4W+omTpM49E3fCbFIDFYSXebEdWlJK3NtJ9JtR8yiMZzM9LYZR5z+DtTnBZH3FHZt0wO+aMijptqNsRhyOmBwPaSZZHKM+vul6zMlrAuqv3kOKf+LtYtTL7LLg="))
